<template>
 
    <!-- 视频监控卡片容器 -->
 
      <div class="video-container">
        <div class="main-layout">
          <!-- 左侧区域（预留，可扩展其他功能） -->
        
          
          <!-- 中间区域（预留，可扩展其他功能） -->
          <div class="middle-sidebar">
            <div class="sidebar-placeholder">
              <!-- 中间区域内容 -->
            </div>
          </div>

          <!-- 右侧主区域（包含控制栏和视频播放区） -->
          <div class="right-sidebar" ref="rightSidebar">
            <!-- 控制区域：模式切换、布局切换、拍照等功能按钮 -->
            <div class="controls">
              <!-- 模式切换：实时/回放 -->
              <el-button-group class="mode-group">
                <el-button 
                  :type="playMode === 'live' ? 'primary' : ''" 
                  @click="switchMode('live')"
                  size="default"  
                >
                  <el-icon><VideoPlay /></el-icon>
                  <span>实时</span>
                </el-button>
                <el-button 
                  :type="playMode === 'playback' ? 'primary' : ''" 
                  @click="switchMode('playback')"
                  size="default"  
                >
                  <el-icon><VideoCamera /></el-icon>
                  <span>回放</span>  
                </el-button>
              </el-button-group>
              
              <!-- 布局切换按钮组：1屏/4屏/9屏 --><!-- 回放模式禁用多屏 -->
              <el-button-group class="layout-group">
                <el-button :type="layoutType === 1 ? 'primary' : ''" @click="changeLayout(1)" size="default">
                  <el-icon><FullScreen /></el-icon>
                  <span>单屏</span>
                </el-button>
                <el-button 
                  :type="layoutType === 4 ? 'primary' : ''" 
                  @click="changeLayout(4)" 
                  size="default"
                  :disabled="playMode === 'playback'"  
                  :tooltip="playMode === 'playback' ? '回放模式下仅支持单屏' : ''"
                >
                  <el-icon><Menu /></el-icon>
                  <span>四屏</span>
                </el-button>
                <el-button 
                  :type="layoutType === 9 ? 'primary' : ''" 
                  @click="changeLayout(9)" 
                  size="default"
                  :disabled="playMode === 'playback'"  
                  :tooltip="playMode === 'playback' ? '回放模式下仅支持单屏' : ''"
                >
                  <el-icon><Grid /></el-icon>
                  <span>九屏</span>
                </el-button>
              </el-button-group>
              
              <!-- 回放模式特有控制（预留，可添加时间选择等） -->
              <div v-if="playMode === 'playback'" class="playback-controls">
              </div>
              
              <!-- 拍照按钮 --><!-- 防止重复点击 -->
              <el-button 
                type="primary" 
                size="default"  
                @click="captureCurrentScreen"
                :loading="isCapturing"  
                class="capture-button"
              >
                <el-icon><Camera /></el-icon>
                <span>拍照</span>
              </el-button>
              
              <!-- 照片面板切换按钮 -->
              <el-button 
                :type="showPhotoPanel ? 'success' : 'default'" 
                size="default"  
                @click="showPhotoPanel = !showPhotoPanel"
              >
                <el-icon><Picture /></el-icon>
                <span>{{ showPhotoPanel ? '隐藏' : '显示' }}</span>
              </el-button>
              
              <!-- 巡检控制区域：开始/停止巡检、巡检设置 --><!-- 回放模式/未加载完成时禁用 -->
              <div class="inspection-controls">
                <el-button-group>
                  <el-button 
                    :type="inspectionStatus.isRunning ? 'danger' : 'success'" 
                    @click="toggleInspection"
                    size="default" 
                    :disabled="playMode === 'playback' || !zonesLoaded"  
                  >
                    <el-icon><VideoPlay v-if="!inspectionStatus.isRunning" /><VideoPause v-else /></el-icon>
                    <span>{{ inspectionStatus.isRunning ? '结束' : '巡检' }}</span>  
                  </el-button>
                  
                  <!-- 巡检设置弹窗 -->
                  <el-popover placement="bottom" width="300" trigger="click">
                    <template #reference>
                      <el-button size="default" :disabled="playMode === 'playback' || !zonesLoaded">  
                        <el-icon><Setting /></el-icon>
                        <span>设置</span>  
                      </el-button>
                    </template>
                    <div class="inspection-settings">
                      <div class="setting-item">
                        <span>巡检间隔(秒):</span>
                        <el-input-number 
                          v-model="inspectionStatus.interval" 
                          :min="5" 
                          :max="60" 
                          size="small"
                        />
                      </div>
                      <div class="setting-item">
                        <span>播放时长(秒):</span>
                        <el-input-number 
                          v-model="inspectionStatus.playDuration" 
                          :min="3" 
                          :max="30" 
                          size="small"
                        />
                      </div>
                      <div class="setting-item">
                        <span>巡检模式:</span>
                        <el-select v-model="inspectionStatus.mode" size="small">
                          <el-option label="顺序巡检" value="sequence" />
                          <el-option label="随机巡检" value="random" />
                        </el-select>
                      </div>
                    </div>
                  </el-popover>
                </el-button-group>
              </div>
            </div>
            
            <!-- 视频区域：包含播放器、加载状态、错误提示等 -->
            <div class="video-area">
              <!-- 加载状态：分区数据未加载完成时显示 -->
              <el-skeleton v-if="!zonesLoaded" class="video-skeleton" :rows="3" />
              
              <!-- 错误状态：分区数据加载失败时显示 -->
              <div v-else-if="zonesError" class="error-state">
                <el-icon><Warning /></el-icon>
                <span>获取分区数据失败: {{ zonesError }}</span>
                <el-button type="primary" size="small" @click="loadZones()">重试</el-button>
              </div>
              
              <!-- 无数据状态：无分区数据时显示 -->
              <el-empty v-else-if="zones.length === 0" description="暂无分区数据" />
              <!-- **********使用专用的deviceChangeKey*********** -->
              <!-- 视频网格容器：根据布局动态渲染播放器 --><!-- 动态应用布局样式（1/4/9屏） --><!-- 动态应用布局样式（1/4/9屏） -->
              <div v-else class="aspect-ratio-container">
                <div 
                  class="video-grid" 
                  :class="`grid-${layoutType}`"  
                  ref="videoGrid" 
                  :key="`grid-${layoutType}-${playMode}-${layoutUpdateKey}-${deviceChangeKey}-${currentZoneIndex}`"    
                >
                  <div 
                    v-for="(device, index) in visibleDevices" 
                    :key="`player-${device.serial}-${index}-${layoutUpdateKey}-${device.serial}-${Date.now()}`"  
                    :id="`ezuikit-player-${index + 1}`"  
                    class="video-item"
                    v-if="item" 
                  >
                    <!-- 设备信息标签：显示设备名称和编号 -->
                    <div class="video-label">
                      <span class="device-name">{{ item.name }}</span>
                      <span class="device-serial">{{ item.serial }}</span>
                    </div>
                    <!-- 回放模式进度条 -->
                    <div class="progress-container" v-if="playMode === 'playback'">
                      <el-slider 
                        v-model="playbackProgress"
                        :min="0"
                        :max="100"
                        :show-tooltip="false"
                        height="4px"
                        @change="handleProgressChange"
                      />
                    </div>
                  </div>
               </div>
              </div>
              
              <!-- 照片列表区域：默认隐藏，通过按钮切换显示 --><!-- 折叠/展开样式 --><!-- 无照片时禁用 -->
              <div 
                class="photos-section" 
                v-if="showPhotoPanel && zonesLoaded"
                :class="{ 'photos-collapsed': !showPhotoPanel }"  
              >
                <div class="photos-header">
                  <el-icon><Picture /></el-icon>
                  <span>照片列表</span>
                  <el-button 
                    type="danger" 
                    size="small" 
                    @click="clearAllPhotos"
                    :disabled="photos.length === 0"  
                  >
                    <el-icon><Delete /></el-icon>
                    <span>清空</span>
                  </el-button>
                </div>
                
                <!-- 照片列表：横向滚动展示 --><!-- 点击查看详情 --><!-- 图片加载失败处理 --><!-- 阻止事件冒泡 -->
                <div class="photo-list">
                  <div 
                    class="photo-item" 
                    v-for="(photo, index) in photos" 
                    :key="index"
                  >
                    <img 
                      :src="photo.url" 
                      alt="截图" 
                      @click="showPhotoDetail(photo)" 
                      @error="handleImageError(photo, $event)"  
                    >
                    <div class="photo-info">
                      <span class="device-name">{{ photo.deviceName }}</span>
                      <span class="timestamp">{{ photo.timestamp }}</span>
                      <div class="photo-actions">
                        <el-button 
                          type="danger" 
                          size="small" 
                          @click.stop="deletePhoto(index)"  
                          :icon="Delete"
                          circle
                        />
                      </div>
                    </div>
                  </div>
                  <el-empty v-if="photos.length === 0" description="暂无照片" />
                </div>
              </div>
              
              <!-- 分区监控选择区域：显示分区和摄像头列表 --><!-- 回放模式禁用 -->
              <div class="zone-selection" v-if="zonesLoaded && zones.length > 0">
                <div class="zone-header">
                  <el-icon><MapLocation /></el-icon>
                  <span>分区监控</span>
                   <el-button 
                    type="primary" 
                    size="small" 
                    @click="showAddCameraDialog"
                    :disabled="playMode === 'playback'"  
                  >
                    <el-icon><Plus /></el-icon>
                    <span>新增摄像头</span>
                  </el-button>
                </div>
                
                <!-- 分区切换按钮 --><!-- 当前分区高亮 -->
                <div class="zone-buttons">
                  <el-button 
                    v-for="(zone, index) in zones" 
                    :key="index"
                    :type="currentZoneIndex === index ? 'primary' : 'default'"  
                    @click="switchZone(index)"
                    size="default"
                    :class="{ 'zone-active': currentZoneIndex === index }"
                  >
                    {{ zone.name }}
                  </el-button>
                </div>
                
                <!-- 摄像头缩略图选择区域：显示当前分区下的所有摄像头 --> <!-- 设备唯一标识 --><!-- 点击切换选中摄像头 --><!-- 选中状态高亮 -->
                <div class="camera-thumbnails">
                  <div 
                    class="camera-thumbnail"
                    v-for="(device, index) in devicesWithSelection"  
                    :key="device.serial"  
                    @click="selectCamera(device.serial)"  
                    :class="{ 'active': device.isSelected }" 
                  >
                  <div class="thumbnail-img">
                        <!-- 缩略图播放器容器 -->
                        <div :id="`thumbnail-player-${device.serial}`" class="thumbnail-player"></div>
                        <!-- 在线状态指示器：绿色=在线，红色=离线 -->
                        <!-- <div class="camera-indicator" :class="{ 'online': isCameraOnline(device.serial) }"></div> -->
                        <!-- 删除摄像头按钮 -->
                        <el-button 
                          type="danger" 
                          size="small" 
                          icon="Delete" 
                          circle
                          class="delete-camera-btn"
                          @click.stop="confirmDeleteCamera(device.serial)" 
                        />
                      </div>
                      <div class="thumbnail-name">{{ device.name }}</div>
                    </div>

                    <!-- 新增摄像头对话框 -->
                    <el-dialog 
                      title="新增摄像头" 
                      v-model="addCameraDialogVisible" 
                      width="400px">
                      <el-form :model="newCameraForm" label-width="80px">
                        
                        <el-form-item label="区域名称" prop="zonename" :rules="[{ required: true, message: '请输入区域' }]">
                          <el-input v-model="newCameraForm.zonename" placeholder="请输入区域名称" />
                        </el-form-item>
                        <el-form-item label="设备名称" prop="name" :rules="[{ required: true, message: '请输入设备名称' }]">
                          <el-input v-model="newCameraForm.name" />
                        </el-form-item>
                        <el-form-item label="设备编号" prop="serial" :rules="[{ required: true, message: '请输入设备编号' }]">
                          <el-input v-model="newCameraForm.serial" />
                        </el-form-item>
                        <el-form-item label="AppKey" prop="appKey" :rules="[{ required: true, message: '请输入AppKey' }]">
                          <el-input v-model="newCameraForm.appKey" />
                        </el-form-item>
                        <el-form-item label="AppSecret" prop="appSecret" :rules="[{ required: true, message: '请输入AppSecret' }]">
                          <el-input v-model="newCameraForm.appSecret" />
                        </el-form-item>
                      </el-form>
                      <template #footer>
                        <el-button @click="addCameraDialogVisible = false">取消</el-button>
                        <el-button type="primary" @click="addCamera">确定</el-button>
                      </template>
                    </el-dialog>
                </div>        
              </div>
            </div>
          </div>
        </div>
      </div>

</template>

<script setup>
import { ref, onMounted, watch, onBeforeUnmount, nextTick, computed, h } from 'vue'
// 导入萤石云播放器SDK
import EZUIKit from 'ezuikit-js'
// 导入Element Plus图标组件
import { 
  FullScreen, Grid, Menu, Warning, 
  VideoPlay, VideoPause, VideoCamera, Delete,
  Picture, Setting, MapLocation, Camera,Download
} from '@element-plus/icons-vue'
// 导入日期处理库
import dayjs from 'dayjs'
// 导入Element Plus组件
import { ElMessage, ElMessageBox, ElButton, ElSkeleton } from 'element-plus'
// 导入API接口函数
import {captureImage, getYSAccessToken, getAllZones, clearCachedAccessToken,getCameraDetail,
  addCameraToZone,removeCameraFromZone
} from '@/api/agriculture/guo/smartScreen/capture.js'

// ******添加专用的设备变化key，用于控制DOM重建时机*****
const deviceChangeKey = ref(0);
// 分区信息相关状态
const zones = ref([])                  // 存储所有分区数据
const zonesLoaded = ref(false)         // 分区数据是否加载完成
const zonesError = ref(null)           // 分区数据加载错误信息

// 设备选择与布局相关状态
const selectedDevice = ref('')         // 当前选中的设备序列号
const layoutType = ref(1)              // 布局类型：1(单屏)、4(四宫格)、9(九宫格)
const videoGrid = ref(null)            // 视频网格容器DOM引用
const rightSidebar = ref(null)         // 右侧边栏DOM引用
const players = new Map();             // 存储播放器实例的Map
const thumbnailPlayers = new Map();    // 存储缩略图播放器实例的Map
let changingLayout = false;            // 布局切换状态标记

// 摄像头状态相关
const cameraStatus = ref({})           // 存储摄像头在线状态

// 录像回放相关状态
const playMode = ref('live')           // 播放模式：'live'(实时) 或 'playback'(回放)
const isPlaying = ref(false)           // 是否正在播放
const playbackDate = ref(dayjs().format('YYYY-MM-DD')) // 回放日期
const playbackTime = ref(dayjs().format('HH:mm:ss'))   // 回放时间
const playbackSpeed = ref('1.0')       // 回放速度
const playbackProgress = ref(0)        // 回放进度
const playbackTimer = ref(null)        // 回放进度定时器

// 照片相关状态
const photos = ref([])                 // 存储拍摄的照片
const showPhotoPanel = ref(false);     // 是否显示照片面板
const isCapturing = ref(false)         // 是否正在拍照（防止重复点击）

// 新增摄像头相关状态
const addCameraDialogVisible = ref(false) // 新增摄像头对话框是否可见
const newCameraForm = ref({               // 新增摄像头表单数据
  zonename: '',
  name: '',
  serial: '',
  appKey: '',
  appSecret: ''
})
// 响应式变量：存储多屏模式下选中的设备序列号
const selectedDevices = ref([]);
const layoutUpdateKey = ref(0);

// 计算返回设备列表
const visibleDevices = computed(() => {
  // 获取当前区域的设备列表
  const currentDevices = devices.value || [];
  
  // 确保currentDevices是数组
  if (!Array.isArray(currentDevices)) {
    console.warn('当前区域设备不是数组', currentDevices);
    return [];
  }
  
  if (layoutType.value === 1 && selectedDevice.value) {
    // 单屏模式：只返回选中的设备
    const selected = currentDevices.find(device => device?.serial === selectedDevice.value);
    return selected ? [selected] : [];
  } else {
    // 多屏模式：返回已选中的设备，如果不足则补充当前区域的其他设备
    if (selectedDevices.value.length > 0) {
      return selectedDevices.value
        .map(serial => currentDevices.find(device => device?.serial === serial))
        .filter(Boolean); // 过滤掉不存在的设备
    }
    // 如果没有选中设备，返回当前区域的前N个设备
    return currentDevices.slice(0, layoutType.value);
  }
});

// 改进初始化播放器
const initPlayers = async () => {
  if (!zonesLoaded.value || !videoGrid.value || !Array.isArray(devices.value) || devices.value.length === 0) {
    console.warn('不满足初始化播放器的条件');
    return;
  }

  // 等待DOM更新完成，确保容器已创建
  await nextTick();
  
  visibleDevices.value.forEach((item, index) => {
    if (!item) return; // 跳过无效设备
    
    const containerId = `ezuikit-player-${index + 1}`;
    const container = document.getElementById(containerId);
    
    if (!container) {
      console.error(`容器 ${containerId} 不存在，无法初始化播放器`);
      // 尝试创建容器元素
      const newContainer = document.createElement('div');
      newContainer.id = containerId;
      newContainer.className = 'video-item';
      videoGrid.value.appendChild(newContainer);
      console.log(`已自动创建缺失的容器 ${containerId}`);
    }
    
    // 初始化播放器
    initPlayer(containerId, item.serial);
  });
};

// 播放下一个巡检设备
const playNextInspectionDevice = async () => {
  if (!inspectionStatus.value.isRunning) return
  
  // 在切换前拍照
  if (inspectionStatus.value.currentIndex >= 0 && players.size > 0) {
    await captureCurrentScreen()
  }
  
  // 获取下一个设备索引
  let nextIndex
  if (inspectionStatus.value.mode === 'random') {
    nextIndex = Math.floor(Math.random() * devices.value.length)
  } else {
    nextIndex = (inspectionStatus.value.currentIndex + 1) % devices.value.length
  }
  
  inspectionStatus.value.currentIndex = nextIndex
  
  // 销毁当前播放器
  await destroyAllPlayers()
  
  // 播放新设备
  const containerId = 'ezuikit-player-1'
  const device = devices.value[nextIndex]
  
  // 更新选中设备
  selectedDevice.value = device.serial
  
  // 仅在设备切换时更新key，触发DOM更新
  deviceChangeKey.value++
  
  // 等待DOM更新完成后再初始化播放器
  await nextTick()
  initPlayer(containerId, device.serial)
  
  // 设置定时器切换到下一个设备
  inspectionStatus.value.timer = setTimeout(() => {
    playNextInspectionDevice()
  }, inspectionStatus.value.playDuration * 1000)
};

// 切换分区
const switchZone = async (index) => {
  if (currentZoneIndex.value === index) return;
  
  // 停止当前播放并销毁播放器
  await destroyAllPlayers();
  destroyThumbnailPlayers();
  
  // 重置设备选择状态（关键修改）
  selectedDevice.value = '';
  selectedDevices.value = [];
  layoutUpdateKey.value++; // 强制更新布局
  
  // 更新当前分区
  currentZoneIndex.value = index;
  
  // 等待DOM更新
  await nextTick();
  
  // 初始化新分区的设备选择
  initSelectedDevices();
  
  // 同步尺寸并初始化播放器
  syncScreenSizes();
  initPlayers();
  initThumbnailPlayers();
  
  ElMessage.success(`已切换到${zones.value[index].name}`);
};

// 修改初始化选中设备
const initSelectedDevices = () => {
  // 只在多屏模式且选中列表为空时初始化
  if (layoutType.value !== 1 && selectedDevices.value.length === 0) {
    const currentDevices = devices.value || [];
    const deviceCount = currentDevices.length;
    
    // 只选中当前区域存在的设备
    const selectCount = Math.min(layoutType.value, deviceCount);
    selectedDevices.value = currentDevices
      .slice(0, selectCount)
      .map(device => device.serial);
    
    // 提示用户设备数量情况
    if (deviceCount < layoutType.value) {
      ElMessage.info(`当前分区只有${deviceCount}个摄像头，已自动选中所有设备`);
    }
  }
};
// 选中摄像头
const selectCamera = async (serial) => {
  // 多屏模式处理
  if (layoutType.value !== 1) {
    const index = selectedDevices.value.indexOf(serial);
    
    // 取消选中逻辑
    if (index > -1) {
      const remainingDevices = devices.value.length;
      const afterRemovalCount = selectedDevices.value.length - 1;
      
      if (remainingDevices <= layoutType.value && afterRemovalCount < remainingDevices) {
        ElMessage.warning(`当前分区只有${remainingDevices}个摄像头，无法取消最后一个选中项`);
        return;
      }
      
      selectedDevices.value.splice(index, 1);
      ElMessage.info(`已取消选择 ${devices.value.find(d => d.serial === serial)?.name}`);
    } else {
      // 添加选中逻辑
      if (selectedDevices.value.length < layoutType.value) {
        selectedDevices.value.push(serial);
        ElMessage.info(`已选择 ${devices.value.find(d => d.serial === serial)?.name}`);
      } else {
        ElMessage.warning(`最多只能选择${layoutType.value}个摄像头`);
        return;
      }
    }
    
    // 关键修复：强制更新布局key，确保DOM完全重建
    layoutUpdateKey.value++;
    // 彻底销毁旧播放器
    await destroyAllPlayers();
    // 等待DOM更新完成（增加延迟确保旧DOM已移除）
    await nextTick();
    await new Promise(resolve => setTimeout(resolve, 80)); // 延长等待时间
    // 同步尺寸并初始化新播放器
    syncScreenSizes();
    initPlayers();
    return;
  }
  
  // 单屏模式处理
  if (selectedDevice.value === serial) return;
  
  // 关键修复：先销毁再延迟初始化，避免新旧实例冲突
  await destroyAllPlayers();
  selectedDevice.value = serial;
  layoutUpdateKey.value++; // 强制重绘
  await nextTick();
  await new Promise(resolve => setTimeout(resolve, 80)); // 确保DOM就绪
  syncScreenSizes();
  initPlayers();
  
  const device = devices.value.find(d => d.serial === serial);
  if (device) {
    ElMessage.info(`已选择 ${device.name}`);
  }
};
// 播放器尺寸
const adjustPlayerSize = (containerId) => {
  const playerData = players.get(containerId);
  if (playerData && playerData.instance) {
    const container = document.getElementById(containerId);
    
    if (container) {
      // 强制尺寸为整数像素，避免浏览器四舍五入偏差
      const rect = container.getBoundingClientRect();
      const width = Math.floor(rect.width); // 取整
      const height = Math.floor(rect.height); // 取整
      
      container.style.width = `${width}px`;
      container.style.height = `${height}px`;
      container.style.minHeight = '0';
      container.offsetHeight; // 触发浏览器重排
    }

    // 调整播放器尺寸（传入整数参数）
    if (playerData.instance.resize) {
      playerData.instance.resize(width, height); // 整数尺寸
    } else if (playerData.instance.adjustSize) {
      playerData.instance.adjustSize();
    } else if (playerData.instance.setPlayerSize) {
      playerData.instance.setPlayerSize(width, height); // 整数尺寸
    }
    
    // 强制重绘
    setTimeout(() => {
      if (container) {
        container.style.transform = 'translateZ(0)';
        container.offsetHeight;
        container.style.transform = '';
      }
    }, 50);
  }
};
// 屏幕尺寸
const syncScreenSizes = () => {
  if (!rightSidebar.value || !videoGrid.value) return;
  
  const sidebarRect = rightSidebar.value.getBoundingClientRect();
  const availableWidth = Math.floor(sidebarRect.width - 40); // 取整避免小数
  const baseWidth = Math.max(availableWidth, 320);
  videoGrid.value.style.width = `${baseWidth}px`;

  // 九屏布局强制行高为整数，避免第一行间隙
  if (layoutType.value === 9 && videoGrid.value) {
    const totalHeight = Math.floor(videoGrid.value.getBoundingClientRect().height);
    const rowHeight = Math.floor(totalHeight / 3); // 确保行高为整数
    // 精确设置每行高度，覆盖默认1fr
    videoGrid.value.style.gridTemplateRows = `repeat(3, ${rowHeight}px)`;
  }
};
// 销毁所有播放器
const destroyAllPlayers = () => {
  return new Promise((resolve) => {
    stopProgressTimer();
    
    players.forEach((playerData, containerId) => {
      try {
        const { instance } = playerData;
        const container = document.getElementById(containerId);
        
        // 关键修复：先移除DOM再销毁实例，避免残留
        if (container && container.parentNode) {
          container.parentNode.removeChild(container);
        }
        
        // 销毁播放器实例
        if (instance) {
          if (typeof instance.stop === 'function') {
            instance.stop().catch(err => console.warn('停止失败:', err));
          }
          if (typeof instance.destroy === 'function') {
            instance.destroy().catch(err => console.warn('销毁失败:', err));
          }
        }
      } catch (e) {
        console.error(`销毁播放器 ${containerId} 失败:`, e);
      }
    });
    
    players.clear();
    resolve();
  });
};
// 切换布局
const changeLayout = async (type) => {
  if (playMode.value === 'playback' && type !== 1) {
    ElMessage.warning('回放模式下仅支持单屏显示');
    return;
  }
  
  if (layoutType.value === type || changingLayout) return;
  changingLayout = true;
  
  try {
    await destroyAllPlayers();
    layoutType.value = type;
    const deviceCount = devices.value.length;
    
    // 多屏模式设备选择逻辑
    if (layoutType.value !== 1) {
      if (deviceCount <= layoutType.value) {
        selectedDevices.value = devices.value.map(device => device.serial);
        ElMessage.info(`当前分区只有${deviceCount}个摄像头，已自动选中所有设备`);
      } else if (selectedDevices.value.length > type) {
        selectedDevices.value = selectedDevices.value.slice(0, type);
      }
    } else {
      // 单屏模式
      selectedDevice.value = selectedDevices.value[0] || devices.value[0]?.serial || '';
    }
    
    initSelectedDevices();
    layoutUpdateKey.value++; // 强制更新布局
    await nextTick();
    await new Promise(resolve => setTimeout(resolve, 100)); // 等待DOM重建
    syncScreenSizes(); // 应用新布局尺寸
    initPlayers();
    
    // 延迟调整，确保渲染完成
    setTimeout(() => {
      syncScreenSizes();
      players.forEach((_, containerId) => {
        adjustPlayerSize(containerId);
      });
    }, 500);
  } catch (error) {
    console.error('布局切换失败:', error);
    ElMessage.error('布局切换失败，请重试');
  } finally {
    changingLayout = false;
  }
};

// 修改计算属性：当前分区的设备列表，添加选中状态标记
const devicesWithSelection = computed(() => {
  if (zones.value.length > 0 && zones.value[currentZoneIndex.value]) {
    return (zones.value[currentZoneIndex.value].devices || []).map(device => ({
      ...device,
      // 单屏模式检查单个选中设备，多屏模式检查是否在选中列表中
      isSelected: layoutType.value === 1 
        ? device.serial === selectedDevice.value
        : selectedDevices.value.includes(device.serial)
    }));
  }
  return [];
});


// 加载分区数据
const loadZones = async () => {
  try {
    zonesLoaded.value = false;
    zonesError.value = null;
    const response = await getAllZones();
    
    if (response.code === 200 && response.data) {
      zones.value = response.data;
    } else {
      throw new Error(response.message || '获取分区数据失败');
    }
  } catch (error) {
    console.error('加载分区数据失败:', error);
    zonesError.value = error.message || '获取分区数据失败';
  } finally {
    zonesLoaded.value = true;
    initSelectedDevices(); // 加载完成后初始化选中设备
  }
};


// 显示新增摄像头对话框
const showAddCameraDialog = () => {
  // 初始化表单数据，默认区域为当前选中区域
  newCameraForm.value = {
    zonename: zones.value[currentZoneIndex.value]?.name || '',
    name: '',
    serial: '',
    appKey: '',
    appSecret: ''
  }
  addCameraDialogVisible.value = true
};

// 添加摄像头到指定分区
const addCamera = async () => {
  try {
    // 调用API保存新摄像头
    const response = await addCameraToZone({
      zonename: newCameraForm.value.zonename,
      name: newCameraForm.value.name,
      serial: newCameraForm.value.serial,
      appKey: newCameraForm.value.appKey,
      appSecret: newCameraForm.value.appSecret
    })
    
    if (response.code === 200) {
      ElMessage.success('摄像头添加成功')
      addCameraDialogVisible.value = false
      
      // 重新加载分区数据
      await loadZones()
      
      // 重新初始化播放器
      await destroyAllPlayers()
      await nextTick()
      initPlayers()
      initThumbnailPlayers()
    } else {
      throw new Error(response.message || '添加摄像头失败')
    }
  } catch (error) {
    console.error('添加摄像头失败:', error)
    ElMessage.error(`添加失败: ${error.message}`)
  }
};

// 确认删除摄像头
const confirmDeleteCamera = (serial) => {
  const device = devices.value.find(d => d.serial === serial)
  if (!device) return
  
  ElMessageBox.confirm(
    `确定要删除摄像头 "${device.name}" 吗?`, 
    '确认删除',
    {
      confirmButtonText: '确定',
      cancelButtonText: '取消',
      type: 'warning'
    }
  ).then(async () => {
    await deleteCamera(serial)
  }).catch(() => {
    // 取消删除，不做处理
  })
};
// 删除摄像头
const deleteCamera = async (serial) => {
  try {
    // 调用API删除摄像头
    const response = await removeCameraFromZone({
      zoneId: zones.value[currentZoneIndex.value].id,
      deviceSerial: serial
    })
    
    if (response.code === 200) {
      ElMessage.success('摄像头删除成功')
      
      // 如果删除的是当前选中的摄像头，重置选中状态
      if (selectedDevice.value === serial) {
        selectedDevice.value = devices.value.length > 1 
          ? devices.value.find(d => d.serial !== serial)?.serial 
          : ''
      }
      
      // 重新加载分区数据
      await loadZones()
      
      // 重新初始化播放器
      await destroyAllPlayers()
      await nextTick()
      initPlayers()
      initThumbnailPlayers()
    } else {
      throw new Error(response.message || '删除摄像头失败')
    }
  } catch (error) {
    console.error('删除摄像头失败:', error)
    ElMessage.error(`删除失败: ${error.message}`)
  }
};

// 处理图片加载错误
const handleImageError = (photo, event) => {
  console.error('图片加载失败:', photo.url)
  event.target.src = 'https://picsum.photos/seed/camera/200/120';
  photo.loadError = true;
};

// 当前选中的分区索引
const currentZoneIndex = ref(0)

//计算属性：当前分区的设备列表
const devices = computed(() => {
  if (zones.value.length > 0 && zones.value[currentZoneIndex.value]) {
    return zones.value[currentZoneIndex.value].devices || []
  }
  return []
});

// 处理全屏状态变化
const handleFullscreenChange = async () => {
  await nextTick();

  // 检查是否退出全屏状态
  const isFullscreen = !!document.fullscreenElement ||
                     !!document.webkitFullscreenElement ||
                     !!document.mozFullScreenElement ||
                     !!document.msFullscreenElement;
  
  // 强制同步网格容器尺寸
  syncScreenSizes();
  
  if (!isFullscreen) {
    // 退出全屏时，重新初始化所有播放器（刷新效果）
    await destroyAllPlayers();
    await nextTick();
    initPlayers();
  } else {
    // 进入全屏时仅调整尺寸
    players.forEach((_, containerId) => {
      adjustPlayerSize(containerId);
    });
  }
  
  // 强制浏览器重绘
  if (videoGrid.value) {
    videoGrid.value.style.display = 'none';
    videoGrid.value.offsetHeight; // 触发重排
    videoGrid.value.style.display = '';
  }
};

// 清空所有照片
const clearAllPhotos = () => {
  if (photos.value.length === 0) return;
  
  ElMessageBox.confirm('确定要删除所有照片吗?', '提示', {
    confirmButtonText: '确定',
    cancelButtonText: '取消',
    type: 'warning'
  }).then(() => {
    photos.value = []
    ElMessage.success('所有照片已删除')
  }).catch(() => {
    // 用户取消删除
  })
};

// 初始化缩略图播放器
const initThumbnailPlayers = async () => {
  // 先销毁已存在的缩略图播放器
  destroyThumbnailPlayers();
  
  // 等待DOM更新
  await nextTick();
  
  // 为每个设备创建缩略图播放器并绑定点击事件
  devices.value.forEach((device) => {
    const containerId = `thumbnail-player-${device.serial}`;
    const container = document.getElementById(containerId);
    
    if (container) {
      // 移除可能存在的旧事件监听器
      const newContainer = container.cloneNode(true);
      container.parentNode.replaceChild(newContainer, container);
      
      // 重新获取容器并绑定新事件
      const freshContainer = document.getElementById(containerId);
      if (freshContainer) {
        // 绑定点击事件，确保使用当前device.serial
        freshContainer.addEventListener('click', (e) => {
          // 检查是否点击的是删除按钮，如果是则不触发选择事件
          if (!e.target.closest('.delete-camera-btn')) {
            selectCamera(device.serial);
          }
        });
        
        // 初始化播放器
        setTimeout(() => {
          initThumbnailPlayer(containerId, device.serial);
        }, 100);
      }
    }
  });
};

// 检查摄像头是否在线
const isCameraOnline = (serial) => {
  return cameraStatus.value[serial] !== undefined ? cameraStatus.value[serial] : true;
};

// 拍照功能
const captureCurrentScreen = async () => {
  const containerId = 'ezuikit-player-1';
  const playerData = players.get(containerId);
  
  if (!playerData || !playerData.instance) {
    ElMessage.error('播放器未初始化');
    return false;
  }
  try {
    isCapturing.value = true;
    const player = playerData.instance;
    const timestamp = dayjs().format('YYYY-MM-DD HH:mm:ss');
    const device = devices.value[inspectionStatus.value.currentIndex];

    // 本地截图
    const localCapture = await player.capturePicture(timestamp);
    const safeLocalCapture = typeof localCapture === 'string' ? localCapture : '';
    
    // 云端截图
    let cloudCapture = null;
    try {
      cloudCapture = await fetchCloudCapture(device.serial);
      cloudCapture = typeof cloudCapture === 'string' ? cloudCapture : '';
    } catch (e) {
      console.warn('云端抓图失败，使用本地截图', e);
    }
    
    // 确定最终图片URL
    let imageUrl = cloudCapture || safeLocalCapture;
    if (typeof imageUrl !== 'string') {
      imageUrl = '';
    }
    // 限制照片数量
    if (photos.value.length > 50) {
      photos.value.pop();
    }
    ElMessage.success('拍照成功');
    return true;
  } catch (error) {
    console.error('拍照失败:', error);
    ElMessage.error(`拍照失败: ${error.message || '未知错误'}`);
    return false;
  } finally {
    isCapturing.value = false;
  }
};

// 调用萤石云API抓图（通过后端代理）
const fetchCloudCapture = async (deviceSerial) => {
  //region 主逻辑
  try {
    //region 获取设备认证信息
    const getDeviceAuthInfo = async (serial) => {
      const deviceDetail = await getCameraDetail(serial);
      if (deviceDetail.code === 200 && deviceDetail.data) {
        return {
          appKey: deviceDetail.data.appKey,
          appSecret: deviceDetail.data.appSecret
        };
      }
      throw new Error(`获取设备${serial}的认证信息失败`);
    };
    //endregion

    // 获取设备认证信息
    const { appKey, appSecret } = await getDeviceAuthInfo(deviceSerial);
        
    //region 获取访问令牌
    const tokenResponse = await getYSAccessToken(appKey, appSecret);
    if (tokenResponse.code !== 200 || !tokenResponse.data?.accessToken) {
      throw new Error(`获取accessToken失败: ${tokenResponse.message || '未知错误'}`);
    }
    const accessToken = tokenResponse.data.accessToken;
    //endregion

    //region 准备请求数据并调用API
    const formData = new URLSearchParams();
    formData.append('accessToken', accessToken);
    formData.append('deviceSerial', deviceSerial);
    formData.append('channelNo', '1');
    
    // 调用封装好的captureImage函数
    const result = await captureImage(formData);
    
    // 处理返回结果
    if (!result.success) {
      throw new Error(result.error || '抓图请求失败');
    }
    //endregion

    // 返回图片URL
    return result.data.picUrl;
  } catch (error) {
    console.error('云端抓图失败:', error);
    throw error; // 继续抛出错误，让调用方可以处理
  }
  //endregion
};

// 查看照片详情（含全屏和下载功能）
const showPhotoDetail = async (photo) => {
  try {
    if (photo.loadError) {
      ElMessage.warning('图片加载失败，无法查看详情');
      return;
    }
    
    // 全屏功能
    const enterImageFullscreen = (imgElement) => {
      if (imgElement.requestFullscreen) {
        imgElement.requestFullscreen();
      } else if (imgElement.webkitRequestFullscreen) {
        imgElement.webkitRequestFullscreen();
      } else if (imgElement.msRequestFullscreen) {
        imgElement.msRequestFullscreen();
      }
    };
    
    // 下载功能
    const downloadImage = (url, filename) => {
      if (url.startsWith('data:image')) {
        const link = document.createElement('a');
        link.download = filename;
        link.href = url;
        document.body.appendChild(link);
        link.click();
        document.body.removeChild(link);
        ElMessage.success('图片下载成功');
        return;
      }
      
      fetch(url)
        .then(response => response.blob())
        .then(blob => {
          const blobUrl = URL.createObjectURL(blob);
          const link = document.createElement('a');
          link.download = filename;
          link.href = blobUrl;
          document.body.appendChild(link);
          link.click();
          document.body.removeChild(link);
          URL.revokeObjectURL(blobUrl);
          ElMessage.success('图片下载成功');
        })
        .catch(error => {
          console.error('图片下载失败:', error);
          ElMessage.error('图片下载失败，请重试');
        });
    };
    
    // 生成下载文件名
    const generateFilename = () => {
      const cleanName = photo.deviceName.replace(/[^\w]/g, '');
      const cleanTime = photo.timestamp.replace(/[:\s]/g, '-');
      return `${cleanName}_${cleanTime}.jpg`;
    };
    
    // 创建自定义关闭按钮的处理函数
    const handleClose = () => {
      // 获取MessageBox实例并关闭
      const messageBox = document.querySelector('.photo-dialog');
      if (messageBox) {
        const closeBtn = messageBox.querySelector('.el-message-box__close');
        if (closeBtn) closeBtn.click();
      }
    };
    
    // 显示照片详情对话框
    await ElMessageBox({
      title: `设备: ${photo.deviceName}`,
      message: h('div', { style: 'max-width: 600px;' }, [
        // 图片区域
        h('div', { 
          style: 'text-align: center; margin: 0 0 15px 0; position: relative;' 
        }, [
          h('img', { 
            src: photo.url, 
            style: `
              max-width: 100%;
              max-height: 50vh;
              display: block;
              margin: 0 auto;
              border-radius: 4px;
              cursor: zoom-in;
            `,
            onError: (e) => {
              e.target.src = 'https://picsum.photos/seed/camera/400/240';
            },
            onClick: (e) => enterImageFullscreen(e.target)
          })
        ]),
        
        // 信息区域
        h('div', { style: 'margin-bottom: 15px;' }, [
          h('p', { 
            style: `
              margin: 0;
              color: #606266;
              font-size: 13px;
              line-height: 1.5;
              display: flex;
              justify-content: space-between;
            ` 
          }, [
            h('span', {}, `拍摄时间: ${photo.timestamp}`),
            h('span', { 
              style: 'color: #909399; font-size: 12px;' 
            }, photo.isCloud ? '云端抓图' : '本地截图')
          ])
        ]),
        
        // 统一按钮区域 - 三按钮横向排列
        h('div', { 
          style: `
            display: flex;
            justify-content: center;
            gap: 10px;
            margin-top: 10px;
          ` 
        }, [
          // 全屏按钮
          h(ElButton, {
            type: 'primary',
            size: 'small',
            onClick: (e) => {
              const img = e.target.closest('.el-message-box').querySelector('img');
              if (img) enterImageFullscreen(img);
            },
            style: 'flex: 1; max-width: 120px;'
          }, [
            h(FullScreen, { style: 'margin-right: 4px; font-size: 14px;' }),
            '全屏'
          ]),
          
          // 下载按钮
          h(ElButton, {
            type: 'success',
            size: 'small',
            onClick: () => downloadImage(photo.url, generateFilename()),
            style: 'flex: 1; max-width: 120px;'
          }, [
            h(Download, { style: 'margin-right: 4px; font-size: 14px;' }),
            '下载'
          ]),
          
          // 关闭按钮
          h(ElButton, {
            type: 'default',
            size: '',
            onClick: handleClose,
            style: 'flex: 1; max-width: 120px;'
          }, [
            '关闭'
          ])
        ])
      ]),
      confirmButtonText: '关闭',
      showCancelButton: false,
      customClass: 'photo-dialog',
      width: 'auto',
      boxStyle: {
        maxWidth: '650px',
        borderRadius: '8px',
        padding: '15px'
      },
      // 隐藏默认的底部按钮栏
      showConfirmButton: false
    });
  } catch (e) {
    if (e !== 'cancel') {
      console.error('显示照片详情出错:', e);
      ElMessage.error('无法查看照片详情');
    }
  }
};

// 删除单张照片
const deletePhoto = (index) => {
  ElMessageBox.confirm('确定要删除这张照片吗?', '提示', {
    confirmButtonText: '确定',
    cancelButtonText: '取消',
    type: 'warning'
  }).then(() => {
    photos.value.splice(index, 1)
    ElMessage.success('照片已删除')
  }).catch(() => {
    // 用户取消删除
  })
};

// 切换巡检状态（开始/停止）
const toggleInspection = () => {
  if (inspectionStatus.value.isRunning) {
    stopInspection()
  } else {
    startInspection()
  }
};

// 开始巡检
const startInspection = async () => {
  // 如果当前是回放模式，切换到实时模式
  if (playMode.value === 'playback') {
    playMode.value = 'live'
    await destroyAllPlayers()
  }
  
  // 确保是单屏模式
  if (layoutType.value !== 1) {
    await changeLayout(1)
  }
  
  inspectionStatus.value.isRunning = true
  inspectionStatus.value.currentIndex = 0
  
  // 开始第一个设备
  playNextInspectionDevice()
};

// 停止巡检
const stopInspection = () => {
  if (inspectionStatus.value.timer) {
    clearTimeout(inspectionStatus.value.timer)
    inspectionStatus.value.timer = null
  }
  inspectionStatus.value.isRunning = false
};


// 巡检相关状态
const inspectionStatus = ref({
  isRunning: false,      // 是否正在巡检
  currentIndex: 0,       // 当前巡检的设备索引
  interval: 10,          // 巡检间隔(秒)
  timer: null,           // 巡检定时器
  playDuration: 5,       // 每个设备播放时长(秒)
  mode: 'sequence'       // 巡检模式: sequence(顺序) | random(随机)
});

// 计算播放URL
const getPlayUrl = async(serial) => {
  const deviceDetail = await getCameraDetail(serial);
  // 确保password存在且为字符串
  const password = deviceDetail.data?.password || '';
  if (typeof password !== 'string') {
    console.error('设备密码不是字符串类型', deviceDetail.data);
    throw new Error('设备密码格式错误');
  }
  
  // 基础URL部分
  const baseUrl = `open.ys7.com/${serial}/`;
  // 根据播放模式拼接不同路径
  const path = playMode.value === 'live' ? '1.live' : '1.cloud.rec';
  
  // 密码不为空时才拼接密码部分
  const url = password 
    ? `ezopen://${password}@${baseUrl}${path}`
    : `ezopen://${baseUrl}${path}`;
  
  return url;
};

// getThumbnailPlayUrl函数，密码为空时不拼接
const getThumbnailPlayUrl = async (serial) => {
  // 首先获取设备详情以获取密码
  const deviceDetail = await getCameraDetail(serial);
  // 确保密码存在且为字符串类型
  const password = deviceDetail.data?.password || '';
  if (typeof password !== 'string') {
    console.error(`设备${serial}的密码不是字符串类型`, deviceDetail.data);
    throw new Error('设备密码格式错误');
  }
  
  // 基础URL部分
  const baseUrl = `open.ys7.com/${serial}/1.live`;
  
  // 密码不为空时才拼接密码部分
  const url = password 
    ? `ezopen://${password}@${baseUrl}`
    : `ezopen://${baseUrl}`;
  
  return url;
};
    
const initThumbnailPlayer = async(containerId, deviceSerial) => {
  const container = document.getElementById(containerId);
  if (!container) {
    console.error(`缩略图容器 ${containerId} 不存在`);
    return null;
  }
  
  container.style.width = '100%';
  container.style.height = '100%';
  container.innerHTML = '';

  try {
    // 获取设备对应的appKey和appSecret
    const getDeviceAuthInfo = async (serial) => {
      const deviceDetail = await getCameraDetail(serial);
      if (deviceDetail.code === 200 && deviceDetail.data) {
        return {
          appKey: deviceDetail.data.appKey,
          appSecret: deviceDetail.data.appSecret
        };
      }
      throw new Error(`获取设备${serial}的认证信息失败`);
    };
    const { appKey, appSecret } = await getDeviceAuthInfo(deviceSerial);
          
    // 获取accessToken
    const tokenResponse = await getYSAccessToken(appKey, appSecret);
    if (tokenResponse.code !== 200 || !tokenResponse.data?.accessToken) {
      throw new Error(`获取accessToken失败: ${tokenResponse.message || '未知错误'}`);
    }
    const accessToken = tokenResponse.data.accessToken;
    
    // 使用await调用异步的getThumbnailPlayUrl
    const url = await getThumbnailPlayUrl(deviceSerial);
    
    // 创建缩略图播放器
    const player = new EZUIKit.EZUIKitPlayer({
      id: containerId,
      url: url,  // 使用获取到的URL
      accessToken: accessToken,
      template: "simple",
    });
    
    // 存储缩略图播放器实例
    thumbnailPlayers.set(containerId, {
      instance: player,
      deviceSerial: deviceSerial
    });
    
    return player;
  } catch (error) {
    console.error(`初始化缩略图播放器失败: ${error.message}`);
    container.innerHTML = `
      <div style="display: flex; justify-content: center; align-items: center; 
                  height: 100%; color: #fff; font-size: 14px;">
        加载失败: ${error.message}
      </div>
    `;
    container.style.backgroundColor = '#000';
    return null;
  }
};

// 销毁所有缩略图播放器
const destroyThumbnailPlayers = () => {
  thumbnailPlayers.forEach((playerData, containerId) => {
    try {
      const { instance } = playerData;
      if (instance) {
        if (typeof instance.stop === 'function') {
          instance.stop().catch(err => console.warn('停止缩略图播放器失败:', err));
        }
        if (typeof instance.destroy === 'function') {
          try {
            instance.destroy();
          } catch (err) {
            console.warn('销毁缩略图播放器失败:', err);
          }
        }
      }
    } catch (e) {
      console.error(`销毁缩略图播放器 ${containerId} 失败:`, e);
    }
  });
  
  thumbnailPlayers.clear();
};

// 启动进度条定时器
const startProgressTimer = (player) => {
  stopProgressTimer()
  playbackTimer.value = setInterval(() => {
    if (player && player.getOSDTime) {
      const osdTime = player.getOSDTime()
      if (osdTime) {
        playbackProgress.value = (playbackProgress.value + 1) % 100
      }
    }
  }, 1000)
};

// 停止进度条定时器
const stopProgressTimer = () => {
  if (playbackTimer.value) {
    clearInterval(playbackTimer.value)
    playbackTimer.value = null
  }
};

// 初始化播放器
const initPlayer = async (containerId, deviceSerial, channelNo = 1) => {
  const maxRetries = 3;
  let retries = 0;

  // 获取设备对应的appKey和appSecret（从设备详情中获取）
  const getDeviceAuthInfo = async (serial) => {
    const deviceDetail = await getCameraDetail(serial);
    if (deviceDetail.code === 200 && deviceDetail.data) {
      return {
        appKey: deviceDetail.data.appKey,
        appSecret: deviceDetail.data.appSecret
      };
    }
    throw new Error(`获取设备${serial}的认证信息失败`);
  };

  const tryGetContainer = async () => {
    const container = document.getElementById(containerId);
    if (container) {
      container.style.width = '100%';
      container.style.height = '100%';
      container.style.minHeight = '0';
      container.innerHTML = '';

      try {
        // 1. 获取设备认证信息
        const { appKey, appSecret } = await getDeviceAuthInfo(deviceSerial);
        
        // 2. 从数据库获取有效accessToken
        const tokenResponse = await getYSAccessToken(appKey, appSecret);
        if (tokenResponse.code !== 200 || !tokenResponse.data?.accessToken) {
          throw new Error(`获取accessToken失败: ${tokenResponse.message || '未知错误'}`);
        }
        const accessToken = tokenResponse.data.accessToken;
        const url = await getPlayUrl(deviceSerial);

        // 3. 创建播放器
        const player = new EZUIKit.EZUIKitPlayer({
          id: containerId,
          url: url,
          accessToken: accessToken, // 使用从数据库获取的有效token
          template: playMode.value === 'live' ? "pcLive" : "pcRec",
          autoPlay: true,
          audio: true,
          download: false,
          downloadRecord: false,
          supportH265:true,
          handleCapturePicture: (res) => {
            if (res.code === 0) {
              const timestamp = dayjs().format('YYYY-MM-DD HH:mm:ss');
              const device = devices.value[inspectionStatus.value.currentIndex];
              photos.value.unshift({
                url: res.data.base64,
                deviceName: device.name,
                timestamp: timestamp,
                deviceSerial: device.serial,
                isCloud: false,
                loadError: false
              });
            }
          },
        });

        // 4. 监听全屏变化事件
        if (player.on) {
          player.on('fullscreenchange', handleFullscreenChange);
        }

        // 5. 存储播放器实例及事件处理
        players.set(containerId, {
          instance: player,
          eventHandlers: {
            play: () => { 
              isPlaying.value = true; 
              startProgressTimer(player); 
            },
            pause: () => { 
              isPlaying.value = false; 
              stopProgressTimer(); 
            },
            stop: () => { 
              isPlaying.value = false; 
              stopProgressTimer(); 
            },
            error: (error) => { 
              // 错误处理：显示提示并更新设备状态
              container.innerHTML = `
                <div style="display: flex; justify-content: center; align-items: center; 
                            height: 100%; color: #fff; font-size: 14px;">
                  播放失败: ${error.message || '未知错误'}
                </div>
              `; 
              container.style.backgroundColor = '#000'; 
              cameraStatus.value[deviceSerial] = false;
              
              // 错误可能是token失效导致，清除缓存重试
              clearCachedAccessToken();
            }
          },
          deviceSerial: deviceSerial
        });

        // 6. 绑定事件监听
        container.addEventListener('play', players.get(containerId).eventHandlers.play);
        container.addEventListener('pause', players.get(containerId).eventHandlers.pause);
        container.addEventListener('stop', players.get(containerId).eventHandlers.stop);
        container.addEventListener('error', players.get(containerId).eventHandlers.error);

        // 7. 初始化后强制调整尺寸
        setTimeout(() => {
          if (player.resize) player.resize();
          else if (player.adjustSize) player.adjustSize();
        }, 300);

        return player;

      } catch (error) {
        // 初始化过程出错处理
        console.error(`播放器初始化失败: ${error.message}`);
        container.innerHTML = `
          <div style="display: flex; justify-content: center; align-items: center; 
                      height: 100%; color: #fff; font-size: 14px;">
            初始化失败: ${error.message}
          </div>
        `;
        container.style.backgroundColor = '#000';
        return null;
      }

    } else if (retries < maxRetries) {
      // 容器未找到，重试
      retries++;
      return new Promise(resolve => {
        setTimeout(() => {
          resolve(tryGetContainer());
        }, 200);
      });
    } else {
      // 重试失败
      const container = document.getElementById(containerId);
      if (container) {
        container.style.backgroundColor = '#000';
        container.innerHTML = `
          <div style="display: flex; justify-content: center; align-items: center; 
                      height: 100%; color: #fff; font-size: 14px;">
            容器 ${containerId} 不存在
          </div>
        `;
      }
      console.error(`容器 ${containerId} 不存在`);
      return null;
    }
  };

  return tryGetContainer();
};

// 切换播放模式（实时/回放）
const switchMode = async (mode) => {
  if (playMode.value === mode) return;
  
  // 如果切换到回放模式，强制设置为单屏
  if (mode === 'playback' && layoutType.value !== 1) {
    await changeLayout(1);
    ElMessage.info('回放模式已自动切换为单屏显示');
  }
  
  playMode.value = mode;
  isPlaying.value = false;
  
  await destroyAllPlayers();
  initPlayers();
};

//处理进度条变化
const handleProgressChange = (val) => {
  console.log('跳转到进度:', val)
};

// 监听选中设备变化
watch(selectedDevice, async (newVal, oldVal) => {
  if (newVal && newVal !== oldVal && zonesLoaded.value) { 
    // 无论布局模式，只要选择变化就重新初始化播放器
    await destroyAllPlayers();
    await nextTick();
    initPlayers();
  }
});
    
// 监听分区变化
watch(currentZoneIndex, async () => {
  // 当分区变化时，重置设备选择为新区的第一个设备
  selectedDevice.value = devices.value[0]?.serial;
  
  // 销毁当前所有播放器并初始化新分区的播放器
  await destroyAllPlayers();
  await nextTick();
  initPlayers();
  // 初始化新分区的缩略图播放器
  initThumbnailPlayers();
});

// 监听分区数据加载完成
watch(zonesLoaded, (loaded) => {
  if (loaded && zones.value.length > 0) {
    // 数据加载完成且有数据时初始化播放器
    initPlayers();
    initThumbnailPlayers();
    
    // 选择第一个设备
    if (devices.value.length > 0) {
      selectedDevice.value = devices.value[0].serial;
    }
  }
});

// 监听倍速变化
watch(playbackSpeed, (newVal) => {
  players.forEach(({ instance }) => {
    if (instance && instance.setPlaySpeed) {
      instance.setPlaySpeed(parseFloat(newVal))
    }
  })
});

// 组件卸载前清理
onBeforeUnmount(() => {
  destroyAllPlayers();
  destroyThumbnailPlayers(); // 销毁缩略图播放器
  stopProgressTimer();
  // 停止巡检
  stopInspection() 
  // 移除全屏事件监听
  document.removeEventListener('fullscreenchange', handleFullscreenChange);
  document.removeEventListener('webkitfullscreenchange', handleFullscreenChange);
  document.removeEventListener('mozfullscreenchange', handleFullscreenChange);
  document.removeEventListener('MSFullscreenChange', handleFullscreenChange);
});

// 组件挂载时初始化
onMounted(async () => {
  // 首先加载分区数据
  await loadZones();
  
  // 初始化设备和播放器
  if (devices.value.length > 0) {
    if (layoutType.value === 1) {
      selectedDevice.value = devices.value[0].serial;
    } else {
      initSelectedDevices();
    }
  }
  
  devices.value.forEach(device => {
    cameraStatus.value[device.serial] = true;
  });
  
  // 初始化尺寸并监听变化
  syncScreenSizes();
  initPlayers();
  initThumbnailPlayers();
  
  // 窗口大小变化时重新计算
  const handleResize = () => {
    syncScreenSizes();
    players.forEach((_, containerId) => {
      adjustPlayerSize(containerId);
    });
  };
  
  window.addEventListener('resize', handleResize);
  
  // 监听右侧容器尺寸变化
  const observer = new ResizeObserver(entries => {
    syncScreenSizes();
  });
  if (rightSidebar.value) {
    observer.observe(rightSidebar.value);
  }
  
  // 组件卸载时清理
  onBeforeUnmount(() => {
    window.removeEventListener('resize', handleResize);
    observer.disconnect();
  });
  
  // 监听全屏状态变化
  document.addEventListener('fullscreenchange', handleFullscreenChange);
  document.addEventListener('webkitfullscreenchange', handleFullscreenChange);
  document.addEventListener('mozfullscreenchange', handleFullscreenChange);
  document.addEventListener('MSFullscreenChange', handleFullscreenChange);
});

</script>
<style scoped>
/* 视频容器样式 */
.video-container {
  display: flex;
  flex-direction: column;
  height: 100%;
}

/* 主布局样式 */
.main-layout {
  display: flex;
  flex: 1;
  height: calc(100vh - 60px);
  gap: 12px;
}

/* 侧边栏样式 */
.left-sidebar, .middle-sidebar {
  width: 200px;
  padding: 0;
  border: 1px solid var(--el-border-color-light);
  border-radius: 4px;
  display: flex;
  flex-direction: column;
  overflow: hidden;
}

.right-sidebar {
  flex: 1;
  display: flex;
  flex-direction: column;
  min-width: 0;
  width: 100%;
  max-width: none;
  padding: 0 10px;
  box-sizing: border-box;
}

/* 视频区域样式 */
.video-area {
  flex: 1;
  min-height: 0;
  display: flex;
  flex-direction: column;
  gap: 15px;
}

/* 视频网格容器样式 - 统一总尺寸 */
.video-grid {
  width: 100% !important; /* 强制占满父容器宽度 */
  max-width: none !important; /* 移除最大宽度限制，避免布局受限 */
  display: grid !important;
  padding: 6px;
  background-color: #f0f2f5; 
  border-radius: 8px;
  box-sizing: border-box;
  gap: 0px;
  margin: 0 auto;
  aspect-ratio: 16/9; /* 保持宽高比 */
  min-height: 0; /* 允许容器高度自适应 */
}

/* 1屏布局 - 占满整个容器 */
.grid-1 {
  grid-template-columns: 1fr;
  grid-template-rows: 1fr;
}

/* 4屏布局 - 2x2四宫格 */
.grid-4 {
  grid-template-columns: repeat(2, 1fr); /* 2列 */
  grid-template-rows: repeat(2, 1fr); /* 2行 */
  gap: 0px;
}

/* 9屏布局 - 3x3九宫格 */
.grid-9 {
  grid-template-columns: repeat(3, 1fr); /* 3列 */
  grid-template-rows: repeat(3, 1fr); /* 3行 */
  gap: 0px;
}

/* 视频项样式 - 所有布局保持一致的内部比例 */
.video-item {
  position: relative;
  background-color: #000;
  border-radius: 4px;
  overflow: hidden;
  width: 100% !important;
  height: 100% !important;
  box-sizing: border-box;
  aspect-ratio: 16/9;
  min-height: 0; /* 允许高度自适应 */
}

/* 固定宽高比容器 - 确保滚动区域不影响总尺寸 */
.aspect-ratio-container {
  flex: 1;
  width: 100%;
  display: flex;
  justify-content: center;
  align-items: flex-start;
  padding: 10px;
  overflow: auto;
  max-height: calc(100vh - 320px);
  scrollbar-width: thin;
  box-sizing: border-box; /* 确保内边距不影响总尺寸 */
}

/* 滚动条样式优化 */
.aspect-ratio-container::-webkit-scrollbar {
  width: 6px;
  height: 6px;
}

.aspect-ratio-container::-webkit-scrollbar-thumb {
  background-color: rgba(144, 147, 153, 0.3);
  border-radius: 3px;
}

/* 响应式适配 - 小屏幕下自动调整最大宽度 */
@media (max-width: 1000px) {
  .video-grid {
    max-width: 90vw; /* 小屏幕下占满可用宽度 */
  }
}

@media (max-width: 768px) {
  /* 小屏幕下优化网格间隙，避免内容拥挤 */
  .video-grid {
    gap: 4px;
    padding: 4px;
  }
}

/* 控制区域整体优化 */
.controls {
  display: flex;
  justify-content: flex-start;
  align-items: center;
  margin-bottom: 12px;
  padding: 10px 15px; /* 增加内边距，提升呼吸感 */
  border-bottom: 1px solid var(--el-border-color-light);
  flex-wrap: wrap; /* 允许自动换行 */
  gap: 12px; /* 增大按钮组间距 */
  background: #f8f9fa;
  border-radius: 6px;
  align-content: center; /* 换行时保持垂直居中 */
}

/* 按钮组容器 */
.mode-group, .layout-group, .inspection-controls {
  display: inline-flex;
  align-items: center;
}

/* 统一按钮大小和样式 */
.controls .el-button {
  padding: 8px 14px; /* 优化按钮内边距 */
  font-size: 13px; /* 统一字体大小 */
  height: 36px; /* 固定按钮高度 */
}

/* 图标与文字间距优化 */
.controls .el-button .el-icon {
  margin-right: 6px; /* 图标与文字间距 */
  font-size: 16px; /* 统一图标大小 */
}

/* 按钮组之间增加分隔线 */
.mode-group + .layout-group,
.layout-group + .capture-button,
.capture-button + .el-button,
.el-button + .inspection-controls {
  position: relative;
}

.mode-group + .layout-group::before,
.layout-group + .capture-button::before,
.capture-button + .el-button::before,
.el-button + .inspection-controls::before {
  content: '';
  position: absolute;
  left: -8px;
  top: 50%;
  transform: translateY(-50%);
  height: 24px;
  width: 1px;
  background-color: var(--el-border-color);
}

/* 巡检控制区域右移，与其他功能区区分 */
.inspection-controls {
  margin-left: auto; /* 自动右对齐 */
  padding-left: 10px;
}

/* 响应式适配 - 小屏幕自动调整 */
@media (max-width: 1400px) {
  .controls {
    gap: 10px;
    padding: 8px 12px;
  }
  
  .controls .el-button {
    padding: 6px 10px;
    font-size: 12px;
  }
  
  /* 缩小图标 */
  .controls .el-button .el-icon {
    font-size: 14px;
    margin-right: 4px;
  }
  
  /* 移除小屏幕下的分隔线 */
  .mode-group + .layout-group::before,
  .layout-group + .capture-button::before,
  .capture-button + .el-button::before {
    display: none;
  }
}

/* 极小屏幕适配 - 按钮组自动换行 */
@media (max-width: 992px) {
  .inspection-controls {
    margin-left: 0;
    width: 100%;
    justify-content: flex-start;
    padding-left: 0;
    margin-top: 8px;
    padding-top: 8px;
    border-top: 1px solid var(--el-border-color-light);
  }
  
  .layout-group {
    order: 1; /* 调整布局按钮组顺序 */
  }
  
  .capture-button {
    order: 2;
  }
  
  .el-button-group:nth-child(2) {
    order: 3;
  }
}

.mode-group, .layout-group {
  margin-right: 6px;
}

.capture-button {
  margin-right: 6px;
}

/* 回放控制区域样式 */
.playback-controls {
  display: flex;
  align-items: center;
  margin-right: 10px;
}

/* 分区监控选择区域 */
.zone-selection {
  padding: 12px;
  background-color: #f8f9fa;
  border-radius: 8px;
  border: 1px solid var(--el-border-color-light);
}

.zone-header {
  display: flex;
  align-items: center;
  margin-bottom: 12px;
  color: var(--el-text-color-primary);
  font-weight: 500;
  gap: 8px;
}

.zone-buttons {
  display: flex;
  gap: 10px;
  flex-wrap: wrap;
  margin-bottom: 16px;
}

.zone-active {
  box-shadow: 0 0 0 2px var(--el-color-primary-light-3);
}

/* 摄像头缩略图选择区域 */
.camera-thumbnails {
  display: flex;
  gap: 12px;
  overflow-x: auto;
  padding: 8px 0;
  scrollbar-width: thin;
}

.camera-thumbnail {
  width: 120px;
  flex-shrink: 0;
  cursor: pointer;
  transition: all 0.2s ease;
  border-radius: 4px;
  padding: 8px;
  border: 1px solid transparent;
}

.camera-thumbnail:hover {
  transform: translateY(-2px);
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
}

.camera-thumbnail.active {
  border-color: var(--el-color-primary);
  background-color: rgba(64, 158, 255, 0.05);
}

.thumbnail-img {
  position: relative;
  width: 100%;
  height: 80px; /* 固定缩略图高度 */
  border-radius: 4px;
  overflow: hidden; /* 关键：隐藏超出容器的内容 */
  margin-bottom: 6px;
  background-color: #000;
  display: flex; /* 辅助居中 */
  align-items: center; /* 垂直居中 */
  justify-content: center; /* 水平居中 */
}

/* 缩略图播放器居中裁剪 */
.thumbnail-player {
  width: 100%;
  height: 100%;
  object-fit: cover; /* 核心属性：保持比例缩放，裁剪超出部分，居中显示 */
  object-position: center; /* 确保内容居中 */
}

/* 摄像头在线状态指示器 */
.camera-indicator {
  position: absolute;
  bottom: 4px;
  right: 4px;
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background-color: #f56c6c;
  border: 1px solid rgba(255, 255, 255, 0.5);
  z-index: 10;
}

.camera-indicator.online {
  background-color: #52c41a;
}

.thumbnail-name {
  font-size: 12px;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  text-align: center;
  margin-top: 8px;
}

/* 照片区域样式 */
.photos-section {
  background-color: #f8f9fa;
  border-radius: 8px;
  border: 1px solid var(--el-border-color-light);
  padding: 12px;
  transition: all 0.3s ease;
  max-height: 300px;
  overflow: hidden;
}

.photos-collapsed {
  max-height: 0;
  padding: 0;
  border: none;
}

.photos-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 12px;
  padding-bottom: 8px;
  border-bottom: 1px solid var(--el-border-color-light);
}

.photo-list {
  display: flex;
  gap: 10px;
  overflow-x: auto;
  padding: 5px 0;
  scrollbar-width: thin;
  max-height: 220px;
  padding-bottom: 10px;
}

.photo-item {
  min-width: 200px;
  transition: box-shadow 0.3s ease;
  border-radius: 4px;
  overflow: hidden;
  background: white;
  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
}

.photo-item:hover {
  box-shadow: 0 4px 16px rgba(0, 0, 0, 0.15);
}

.photo-item img {
  width: 100%;
  height: 120px;
  object-fit: cover;
  display: block;
  background-color: #f0f0f0;
}

.photo-info {
  padding: 6px 8px;
  background: var(--el-bg-color);
  display: flex;
  justify-content: space-between;
  align-items: center;
  font-size: 12px;
}

.device-name {
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  max-width: 100px;
}

.timestamp {
  font-size: 11px;
  color: #666;
  margin: 0 8px;
}

/* 进度条容器 */
.progress-container {
  position: absolute;
  bottom: 0;
  left: 0;
  right: 0;
  padding: 0 8px 8px;
  z-index: 1;
}

/* 视频标签样式 */
.video-label {
  position: absolute;
  top: 8px;
  left: 8px;
  color: white;
  background-color: rgba(0, 0, 0, 0.5);
  padding: 4px 8px;
  border-radius: 4px;
  font-size: 12px;
  z-index: 10;
  max-width: calc(100% - 16px);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.sidebar-placeholder {
  flex: 1;
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
  color: var(--el-text-color-secondary);
  gap: 8px;
}

/* 加载和错误状态样式 */
.video-skeleton {
  flex: 1;
  border-radius: 8px;
  margin: 10px;
}

.error-state {
  flex: 1;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 12px;
  padding: 20px;
  color: #f56c6c;
}

.error-state .el-icon {
  font-size: 20px;
}

/* 响应式调整 */
@media (max-width: 1600px) {
  .left-sidebar, .middle-sidebar {
    width: 180px;
  }
  .right-sidebar {
    max-width: calc(100% - 384px);
  }
}

/* 摄像头删除按钮样式 */
.delete-camera-btn {
  position: absolute;
  top: 4px;
  right: 4px;
  width: 20px;
  height: 20px;
  padding: 0;
  opacity: 0;
  transition: opacity 0.3s ease;
  z-index: 20;
}

.camera-thumbnail:hover .delete-camera-btn {
  opacity: 1;
}
</style>
